package com.hong.utils.locks;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Auther: Administrator
 * @Date: 2018/7/23 13:14
 * @Description:
 */
public class ReentrantLockExample {

    private static final ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        /*IntStream.range(0,2).forEach(i->new Thread(){
            @Override
            public void run() {
                needLockBySync();
            }
        }.start());*/
        /*Thread thread = new Thread() {
            @Override
            public void run() {
                testUnInterruptibly();
            }
        };
        thread.start();
        TimeUnit.SECONDS.sleep(1);


        Thread thread1  = new Thread(()->testUnInterruptibly());
        thread1.start();
        TimeUnit.SECONDS.sleep(1);

        thread1.interrupt();
        System.out.println("====================");*/

       /* Thread thread1 = new Thread(()->testTryLock());
        thread1.start();

        TimeUnit.SECONDS.sleep(1);

        Thread thread2 = new Thread(()->testTryLock());
        thread2.start();*/

        Thread thread1 = new Thread(()->testUnInterruptibly());
        thread1.start();

        TimeUnit.SECONDS.sleep(1);

        Thread thread2 = new Thread(()->testUnInterruptibly());
        thread2.start();
        TimeUnit.SECONDS.sleep(1);
        /*返回等待获取此锁的线程数的估计。 */
        Optional.of(lock.getQueueLength()).ifPresent(System.out::println);
        /*查询是否有线程正在等待获取此锁。 */
        Optional.of(lock.hasQueuedThreads()).ifPresent(System.out::println);
        /*查询当前线程对此锁的暂停数量。 */
        Optional.of(lock.getHoldCount()).ifPresent(System.out::println);
        /*查询给定线程是否等待获取此锁。 */
        Optional.of(lock.hasQueuedThread(thread1)).ifPresent(System.out::println);
        /*查询此锁是否由任何线程持有。 */
        Optional.of(lock.isLocked()).ifPresent(System.out::println);
    }


    public static void testTryLock(){
        if(lock.tryLock()){
            try {
                Optional.of("The thread-"+Thread.currentThread().getName()+" get lock will do woring.").ifPresent(System.out::println);
                while (true){

                }
            }finally {
                lock.unlock();
            }
        }else{
            Optional.of("The thread-"+Thread.currentThread().getName()+" not get lock.").ifPresent(System.out::println);
        }


    }

    public static void testUnInterruptibly(){
        Optional.of(Thread.currentThread().getName()+":"    +lock.getHoldCount()).ifPresent(System.out::println);
        try {
            lock.lockInterruptibly();
            Optional.of("The thread-"+Thread.currentThread().getName()+" get lock will do woring.").ifPresent(System.out::println);
            while (true){

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void needLock(){
        try {
            lock.lock();
            Optional.of("The thread-"+Thread.currentThread().getName()+" get lock will do woring.").ifPresent(System.out::println);
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void needLockBySync(){
        synchronized (ReentrantLockExample.class){
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
